using System;
using System.Diagnostics;
using System.Collections;
using System.ComponentModel;
//using Magic.Parser;

namespace OsdmSoftware.CommonLibrary
{
	public class TranslatorException: ApplicationException
	{
		public PChar StartPos, EndPos;
		public TranslatorException(string Message, PChar StartPos, PChar EndPos):
			base(Message)
		{
			this.StartPos = StartPos;
			this.EndPos = EndPos;
		}

		public TranslatorException(string Message, object[] Arguments, PChar StartPos, PChar EndPos):
			base(String.Format(Message, Arguments))
		{
			this.StartPos = StartPos;
			this.EndPos = EndPos;
		}
	}

    public struct LineColumn
    {
        public int Line;
        public int Column;

        public LineColumn(int line, int column)
        {
            Line = line;
            Column = column;
        }

        public override string ToString()
        {
            return "line " + Line.ToString() + " column " + Column.ToString();
        }
    }

	public struct PChar
	{
		public String SourceText;
		public int Pos;
		public PChar(String sourceText, int pos)
		{
			this.SourceText = sourceText;
			this.Pos = pos;
		}

		public PChar(String sourceText): this(sourceText, 0)
		{
		}

		public char Current { get { return Pos >= SourceText.Length ? Char.MinValue : SourceText[Pos]; } }
		public void Move() { Pos ++; }
		public void Move(int i) { Pos += i; }

		public string GetBeginning(PChar EndPos)
		{
			Trace.Assert(this.SourceText == EndPos.SourceText);
			return SourceText.Substring(this.Pos, EndPos.Pos - this.Pos);
		}

		public void SkipSet(PChar StartPos, SetOfChar Set)
		{
			while(Set.Contains(Current)) Move();
		}

		public void SkipCharsUntilOneOf(PChar StartPos, SetOfChar EndSet)
		{
			while(Current != Char.MinValue && ! EndSet.Contains(Current)) Move();
		}

		public void SkipCharsUntil(PChar StartPos, Char EndChar)
		{
			while(Current != Char.MinValue && Current != EndChar) Move();
		}

		public string ParseNumber(PChar StartPos, Char DecimalSeparator)
		{
			this = StartPos;
			if (this.Current == '-') this.Move();
			while (Char.IsDigit(this.Current)) this.Move();
			if (this.Current == DecimalSeparator)
			{
				this.Move();
				while (Char.IsDigit(this.Current)) this.Move();
			}

			if (Char.ToUpper(this.Current) == 'E')
			{
				this.Move();
				if (this.Current == '-') this.Move();
				while (Char.IsDigit(this.Current)) this.Move();
			}

			return StartPos.GetBeginning(this);
		}
        
		public string ParseQuotedString(PChar StartPos, Char Quote)
		{
			System.Text.StringBuilder b = new System.Text.StringBuilder();
			while (true)
			{
				if (this.Current == Quote)
				{
					this.Move();
					if (this.Current == Quote)
					{
						b.Append(Quote);
						this.Move();
					}
					else
					{
						break;
					}
				}
				else if (this.Current == Char.MinValue)
				{
					throw new TranslatorException("No matching quote", StartPos, this);
				}
				else
				{
					b.Append(this.Current);
					this.Move();
				}
			}

			return b.ToString();
		}

        public LineColumn GetLineColumn()
        {
            int line = 1;
            int column = 1;

            PChar pos1 = new PChar(SourceText);
            while (pos1.Pos != this.Pos)
            {
                if (pos1.Current == '\n')
                {
                    line++;
                    column = 0;
                }

                column++;
                pos1.Move();
            }

            return new LineColumn(line, column);
        }
	}
}